import java.util.concurrent.PriorityBlockingQueue;

class MyTask implements Comparable<MyTask>{
    public Runnable runnable;
    public long time;

    //构造方法
    //delay 单位 毫秒
    public MyTask(Runnable runnable, long delay){
        this.runnable = runnable;
        time = System.currentTimeMillis() + delay;
    }

    @Override
    //优先级队列存放MyTask的对象，是需要比较方法的
    public int compareTo(MyTask o) {
        return (int)(this.time - o.time);
    }


}

class MyTimer {
    private PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();

    private Object locker = new Object();
    public void schedule(Runnable runnable, long delay){
        MyTask myTask = new MyTask(runnable,delay);
        queue.put(myTask);

        //如果新创建的任务等待时间比之前的任何一个任务都要短，那么这里唤醒wait，线程继续往下走的时候
        //取的就是这个新加入的任务了！、
        synchronized (locker){
            locker.notify();
        }
    }

    // 在这里构造线程, 负责执行具体任务了.
    public MyTimer(){
        Thread t1 = new Thread(() -> {
            while(true){
                try {
                    synchronized (locker){
                        MyTask myTask = queue.take();
                        long currentTime = System.currentTimeMillis();
                        if(myTask.time <= currentTime){
                            myTask.runnable.run();
                        }else{
                            //时间还没到，把拿出来的任务再塞回去！
                            queue.put(myTask);
                            //由于这是个循环，再塞回去之后，下一个循环又再取出来，但时间依旧还有好久才到
                            //这会让cpu在等待的时间里，反复取任务，又反复塞回去，忙等！！
                            //所以我们最好让线程在这个时间里不再参与cpu调度
                            locker.wait(myTask.time - currentTime);
                        }
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
    }


}



public class ThreadDemo2 {
    public static void main(String[] args) {
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("♥♥♥♥♥");
            }
        },4000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("♥♥♥♥");
            }
        },3000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("♥♥♥");
            }
        },2000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("♥♥");
            }
        },1000);

        System.out.println("♥");
    }

}
